package se.webbzon.boltzmann.battle.object.status;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import se.webbzon.boltzmann.battle.property.BattleBuff;
import se.webbzon.boltzmann.battle.property.BattleBuffType;
import se.webbzon.boltzmann.resource.Resources;
import se.webbzon.oschi01.worldarea.WorldArea;
import se.webbzon.oschi01.worldobject.WorldMovableObject;
import se.webbzon.oschi01.worldobject.WorldObject;
import se.webbzon.oschi01.worldobject.appearance.AbstractAppearance3D;
import se.webbzon.oschi01.worldobject.appearance.Appearance3D;
import se.webbzon.oschi01.worldobject.appearance.GroupAppearance3D;
import se.webbzon.oschi01.worldobject.appearance.SimpleAppearance3D;
import se.webbzon.oschi01.worldobject.appearance.SimpleGroupAppearance3D;
import se.webbzon.oschi01.worldobject.appearance.XYPlaneAppearance3D;

public class BattleStatusBuff extends WorldMovableObject {
	
	// The rendering order of this status buff bubble
	private static final int renderingOrder = 2;
	
	// The index of the status buff bubble
	private int index;
	
	// The type of the battle buff
	private final BattleBuffType type;
	
	// A timer used when the status buff bubble has been expired
	private int expireTimer;

	/*============================================================
	Constructors
	============================================================*/
	
	/** Creates a new status buff bubble. **/
	public BattleStatusBuff(int index, BattleBuff buff) {
		super(WorldObject.onStep, createAppearance());
		type = buff.getType();
		expireTimer = -1;
		
		setIndex(index);
	}
	
	/*============================================================
	Public Methods
	============================================================*/
	
	/** Returns the type of the buff associated with this status buff bubble. **/
	public BattleBuffType getType() {
		return type;
	}
	
	/** Returns the index of the status buff bubble. **/
	public int getIndex() {
		return index;
	}
	
	/** Sets the index of the status buff bubble. **/
	public void setIndex(int index) {
		this.index = index;
		updateAppearance(index);
	}
	
	/** Destroys the status buff bubble within the given time due to expire. **/
	public void expire(int time) {
		expireTimer = time;
		List<Appearance3D> appearances = 
				((SimpleGroupAppearance3D) getAppearance()).getAppearances();
		Iterator<Appearance3D> it = appearances.iterator();
		SimpleAppearance3D background = (SimpleAppearance3D) it.next();
		SimpleAppearance3D foreground = (SimpleAppearance3D) it.next();
		background.setTransparency(0.5f);
		foreground.setTransparency(0.5f);
		setVelocity(-0.03,0.03,0);
	}
	
	@Override public void onStep(WorldArea world) {
		if (expireTimer >= 0) {
			if (expireTimer == 0) {
				getGroup().removeInstance(this);
				world.destroyInstance(this);
			}
			expireTimer--;
		}
	}
	
	/*============================================================
	Private Methods
	============================================================*/
	
	/** Updates the appearance of the status buff bubble. **/
	private void updateAppearance(int index) {
		List<Appearance3D> appearances = 
				((SimpleGroupAppearance3D) getAppearance()).getAppearances();
		Iterator<Appearance3D> it = appearances.iterator();
		SimpleAppearance3D background = (SimpleAppearance3D) it.next();
		SimpleAppearance3D foreground = (SimpleAppearance3D) it.next();
		
		if (index < 4) {
			final boolean lower = (index == 0);
			background.setTextureIndex(lower ? 0 : 1);
			foreground.setTextureIndex(type.getId()-1);
			foreground.setHOffset(-0.1);
			foreground.setVOffset(lower ? -0.2 : 0);
			setPosition(-1.5,index,0);
		} else {
			final int mod = index % 2;
			final boolean lower = (mod == 0);
			background.setTextureIndex(2 + (lower ? 0 : 1));
			foreground.setTextureIndex(type.getId()-1);
			foreground.setHOffset(0.1);
			foreground.setVOffset(lower ? -0.2 : 0);
			setPosition(-0.5 + index/2,mod,0);
		}
	}
	
	/** Creates the appearance of the status buff bubble. **/
	private static final AbstractAppearance3D createAppearance() {
		List<Appearance3D> appearances =
				new ArrayList<Appearance3D>();
		
		// Create background
		SimpleAppearance3D background = 
				new XYPlaneAppearance3D(0,
										SimpleAppearance3D.TRANSPARENCY,false);
		background.setTransparency(0.2f);
		background.setTextureSet(Resources.getTextureSet("buff_background"));
		
		// Create foreground
		SimpleAppearance3D foreground = 
				new XYPlaneAppearance3D(1,
										SimpleAppearance3D.TRANSPARENCY + 
										SimpleAppearance3D.LAYERS +
										SimpleAppearance3D.TEXTURE_TRANSLATION,false);
		foreground.setTextureSet(Resources.getTextureSet("buff"));
		foreground.setLayer(0, 0, 1);
		
		appearances.add(background);
		appearances.add(foreground);
		return new SimpleGroupAppearance3D(	renderingOrder,
											GroupAppearance3D.TRANSPARENCY,
											appearances);
	}

}
